#include "csgtree.h"

CSGTree::CSGTree(){
}

void CSGTree::organizeTransformations(){
    //The organization of transformations is done by descending them to all the primitives that they affect. This
    //procedure permits all transformated points's isovalues to be evaluated only verifying the child node of the
    //transformation.


}

double CSGTree::calcScalarFieldValue(XYZ &p){
    //Do a post-order traversal on the CSGTree to determine the implicit value for point p.
    return postOrderTraversal(m_csgTree.begin() , p);
}

double CSGTree::postOrderTraversal(Tree::iterator_base itRoot , XYZ &p){
    //Do a post order traversal on the CSGTree with the vertex pointed by itRoot as root.

    Tree::post_order_iterator it;
    stack<double> values;
    double fImplicitValue0 , fImplicitValue1;
    CSGNode *pNode;
    string sType;
    XYZ pTransformed;

    Tree tree = Tree(itRoot);

    for(it = tree.begin_post() ; it != tree.end_post() ; it++){
        pNode = (*it);
        sType = string(typeid(*pNode).name());

        //cout << sType << endl;

        if(sType.find("CSGBox") != sType.npos || sType.find("CSGCylinder") != sType.npos || sType.find("CSGSphere") != sType.npos){
            CSGSolid *pSolid = dynamic_cast<CSGSolid*>(pNode);
            fImplicitValue0 = pSolid->evaluateEquation(p);
            values.push(fImplicitValue0);
        }
        else if(sType.find("CSGTransformation") != sType.npos){
            CSGTransformation *pTransformation = dynamic_cast<CSGTransformation*>(pNode);
            pTransformed = pTransformation->transform(p);
            fImplicitValue0 = postOrderTraversal(it.begin() , pTransformed);
            values.push(fImplicitValue0);
        }
        else{
            CSGOperation *pOperation = dynamic_cast<CSGOperation*>(pNode);
            fImplicitValue1 = values.top(); values.pop();
            fImplicitValue0 = values.top(); values.pop();
            values.push(pOperation->doCSGOperation(fImplicitValue0 , fImplicitValue1));
        }
    }
    //cout << "Ending traversal" << endl << endl;
    p.val = values.top();

    return p.val;
}
